Syntax10.Scn.Fnt Syntax10b.Scn.Fnt FoldElems Syntax10.Scn.Fnt (* standard colors *) Syntax10.Scn.Fnt (*MS-Windows Colors*) MODULE Mines; (** Oberon-Mines V1.32 (C) 1 Oct 95 by Ralf Degner *) (* If you use MacOberon or the Ceres replace Input.TimeUnit by 300 *) IMPORT Oberon, Texts, Display, MenuViewers, TextFrames, Input, Fonts, Viewers, Files; CONST (* the colors of Mines with Mines.Pal *) black=Display.white; red=1; yellow=4; lightgray=12; midgray=13; darkgray=14; Col1=3; Col2=2; Col3=red; Col4=9; Col5=7; Col6=5; Col7=6; Col8=black; (* the colors of Mines for Windows *) (*black=Display.white; red=1; yellow=10; lightgray=11; midgray=12; darkgray=14; Col1=3; Col2=5; Col3=red; Col4=6; Col5=4; Col6=8; Col7=7; Col8=black;*) Menu = "System.Close System.Copy System.Grow Mines.Pause Mines.Beginner Mines.Advanced Mines.Expert Mines.Max Mines.Score"; KastenBreite=16;ObenPlatz=25; UntenPlatz=4;SeitenPlatz=4; KastenPlatz*=KastenBreite+1;KB=KastenBreite; MinKastenAnz=7;CharBreite=8; FeldPtr* = POINTER TO ARRAY OF ARRAY OF SHORTINT; String = ARRAY 32 OF CHAR; Data* = POINTER TO DataDesc; DataDesc* = RECORD XKastenAnz*,YKastenAnz*: INTEGER; Aktiv*, Pause*, StartPlay*: BOOLEAN; Feld*: FeldPtr; Time*, Count*, Mines*: LONGINT; Quote*, Mode*: INTEGER; END; Frame* = POINTER TO FrameDesc; FrameDesc* = RECORD(Display.FrameDesc) SeitenOffset*, UntenOffset*: INTEGER; LastModMsg: BOOLEAN; d*: Data; END; MinerMsg = RECORD(Display.FrameMsg) d*: Data; END; PlotNewMsg = RECORD(MinerMsg) END; PlotKastenMsg* = RECORD(MinerMsg) x*, y*: INTEGER; END; NeuesFeldMsg = RECORD(MinerMsg) Change: BOOLEAN; END; RePlotMsg = RECORD(MinerMsg) All: BOOLEAN; END; TimeMsg = RECORD(MinerMsg) id: LONGINT; Count: INTEGER; END; UsedFont: Fonts.Font; W: Texts.Writer; TimeTask: Oberon.Task; seed, StartTime, LastTime: LONGINT; HiTime: ARRAY 3 OF LONGINT; HiName: ARRAY 3 OF String; Name: String; ScoreFile: Files.File; ScoreRider: Files.Rider; Color, UseTimeTask, TimeTaskRuns, PauseFlag: BOOLEAN; Colors: ARRAY 8 OF INTEGER; Dummy: INTEGER; TimeUnit: LONGINT; (* data for patterns *) HappyData, SadData, BackData, GotItData, PauseData: ARRAY 17 OF SET; HappyPat, SadPat, BackPat, GotItPat, PausePat: LONGINT; Data1, Data2, Data3, Data4: ARRAY 13 OF SET; Pat: ARRAY 5 OF LONGINT; (* clear HiScore *) PROCEDURE ClearHi; VAR d: INTEGER; BEGIN FOR d:=0 TO 2 DO HiTime[d]:=999999; HiName[d]:="Amiga" END ClearHi; (* store HiScore *) PROCEDURE SaveHi(Register: BOOLEAN); VAR d: INTEGER; BEGIN Files.Set(ScoreRider, ScoreFile, 0); Files.WriteBool(ScoreRider, Color); Files.WriteBool(ScoreRider, UseTimeTask); FOR d:=0 TO 2 DO Files.WriteLInt(ScoreRider, HiTime[d]); Files.WriteBytes(ScoreRider, HiName[d], 32); END; IF Register THEN Files.Register(ScoreFile) ELSE Files.Close(ScoreFile) END END SaveHi; (* load HiScore *) PROCEDURE LoadHi; VAR d: INTEGER; BEGIN ClearHi(); ScoreFile:=Files.Old("Mines.Score"); IF ScoreFile=NIL THEN ScoreFile:=Files.New("Mines.Score"); SaveHi(TRUE) ELSE Files.Set(ScoreRider, ScoreFile, 0); Files.ReadBool(ScoreRider, Color); Files.ReadBool(ScoreRider, UseTimeTask); FOR d:=0 TO 2 DO Files.ReadLInt(ScoreRider, HiTime[d]); Files.ReadBytes(ScoreRider, HiName[d], 32) END END LoadHi; (* produces random numbers *) PROCEDURE Random(Ein: INTEGER):INTEGER; CONST a=16807; m=2147483647; q=m DIV a; r=m MOD a; VAR g: LONGINT; BEGIN g:=a*(seed MOD q)-r*(seed DIV q); IF g>0 THEN seed:=g ELSE seed:=g+m END; RETURN SHORT(seed) MOD Ein END Random; (* stop the TimeTask *) PROCEDURE StopTask*; BEGIN IF TimeTaskRuns THEN Oberon.Remove(TimeTask); TimeTaskRuns:=FALSE END StopTask; (* the task that sends a TimeMsg every second *) PROCEDURE TheTimeTask; VAR timsg: TimeMsg; BEGIN IF Input.Time()>LastTime THEN LastTime:=LastTime+TimeUnit; timsg.id:=StartTime; timsg.Count:=0; Viewers.Broadcast(timsg); IF timsg.Count=0 THEN StopTask() END END TheTimeTask; (* start the TimeTask *) PROCEDURE StartTask; BEGIN IF ~TimeTaskRuns THEN NEW(TimeTask); TimeTask.safe:=FALSE; TimeTask.handle:=TheTimeTask; Oberon.Install(TimeTask); LastTime:=Input.Time(); TimeTaskRuns:=TRUE END StartTask; (* draw box at top of the field *) PROCEDURE PlotSmily(f: Frame; Smile: BOOLEAN); VAR XPos, YPos, Col: INTEGER; BEGIN IF f.H>ObenPlatz THEN IF f.W>30 THEN YPos:=f.Y+f.H-ObenPlatz+3; XPos:=f.W DIV 2-10+f.X; IF Color THEN Display.ReplConst(lightgray, XPos, YPos, 20, 20, Display.replace); Display.ReplConst(darkgray, XPos+1, YPos, 19, 19, Display.replace); Display.ReplConst(midgray, XPos+1, YPos+1, 18, 18, Display.replace); Display.CopyPattern(yellow, BackPat, XPos+2, YPos+2, Display.paint); Col:=black ELSE Display.ReplConst(Display.white, XPos, YPos, 20, 20, Display.replace); Display.ReplConst(Display.black, XPos+1, YPos+1, 18, 18, Display.replace); Col:=Display.white; END; IF f.d.Pause THEN Display.CopyPattern(Col, PausePat, XPos+2, YPos+2, Display.paint) ELSE IF Smile THEN Display.CopyPattern(Col, HappyPat, XPos+2, YPos+2, Display.paint) ELSE Display.CopyPattern(Col, SadPat, XPos+2, YPos+2, Display.paint) END END END END PlotSmily; (* clear a frame *) PROCEDURE ClearFrame(f: Frame; Smile: BOOLEAN); BEGIN Oberon.RemoveMarks(f.X, f.Y, f.W, f.H); Display.ReplConst(Display.black, f.X, f.Y, f.W, f.H, Display.replace); f.SeitenOffset:=(f.W-f.d.XKastenAnz*KastenPlatz) DIV 2 +f.X; f.UntenOffset:=f.Y+f.H-ObenPlatz-f.d.YKastenAnz*KastenPlatz; PlotSmily(f, Smile); END ClearFrame; (* copy frame with same data *) PROCEDURE CopyMe(f: Frame): Frame; VAR nf: Frame; BEGIN NEW(nf);IF nf=NIL THEN RETURN NIL;END; nf.handle:=f.handle; nf.d:=f.d;nf.LastModMsg:=TRUE; RETURN nf; END CopyMe; (* clear a box *) PROCEDURE ClearKasten(f: Frame; x, y: INTEGER; Color: BOOLEAN); VAR dumx, dumy: INTEGER; BEGIN dumx:=f.SeitenOffset+x*KastenPlatz-KastenBreite; dumy:=f.UntenOffset+y*KastenPlatz-KastenBreite; IF Color THEN Display.ReplConst(darkgray, dumx, dumy, KB, KB, Display.replace); Display.ReplConst(lightgray, dumx+1, dumy, KB-1, KB-1, Display.replace); Display.ReplConst(midgray, dumx+1, dumy+1, KB-2, KB-2, Display.replace) ELSE Display.ReplConst(Display.black, dumx, dumy, KB, KB, Display.replace) END ClearKasten; (* draw not selected box *) PROCEDURE BlockKasten(f: Frame; x, y: INTEGER; Color: BOOLEAN; col: INTEGER); VAR dumx, dumy: INTEGER; BEGIN dumx:=f.SeitenOffset+x*KastenPlatz-KastenBreite; dumy:=f.UntenOffset+y*KastenPlatz-KastenBreite; IF Color THEN Display.ReplConst(lightgray, dumx, dumy, KB, KB, Display.replace); Display.ReplConst(darkgray, dumx+1, dumy, KB-1, KB-1, Display.replace); Display.ReplConst(midgray, dumx+1, dumy+1, KB-2, KB-2, Display.replace) ELSE Display.ReplConst(Display.black, dumx, dumy, KB, KB, Display.replace); Display.ReplConst(col, dumx+1, dumy+1, KB-2, KB-2, Display.replace) END BlockKasten; (* draw char at box *) PROCEDURE DrawChar(f: Frame; ch: CHAR; XKasten, YKasten: INTEGER; Color: BOOLEAN; col: INTEGER); Pat: Display.Pattern; dx, x, y, w, h: INTEGER; dumx, dumy: INTEGER; BEGIN Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat); ClearKasten(f, XKasten, YKasten, Color); dumx:=f.SeitenOffset+XKasten*KastenPlatz-KastenBreite+(KB-w) DIV 2; dumy:=f.UntenOffset+YKasten*KastenPlatz-KastenBreite+(KB-h) DIV 2; IF Color THEN col:=Colors[ORD(ch)-49]; END; Display.CopyPattern(col, Pat, dumx, dumy, Display.paint); END DrawChar; (* draw char at x y to display *) PROCEDURE DrawZahl(ch: CHAR; XPos, YPos: INTEGER); Pat: Display.Pattern; dx, x, y, w, h: INTEGER; BEGIN Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat); IF Color THEN h:=black ELSE h:=Display.white; END; Display.CopyPattern(h, Pat, XPos+x, YPos+y, Display.paint); END DrawZahl; (* draw LONGINT *) PROCEDURE DrawInt(x, y: INTEGER; Zahl: LONGINT; DrawInt: BOOLEAN); VAR Col, Anz: INTEGER; BEGIN Anz:=4; IF Color THEN Col:=midgray ELSE Col:=Display.black; END; Display.ReplConst(Col, x, y, Anz*CharBreite+10, KastenBreite-2, Display.replace); IF DrawInt THEN IF Zahl<0 THEN DrawZahl("-", x+2, y+1); Zahl:=ABS(Zahl); END; REPEAT DrawZahl(CHR(Zahl MOD 10+48), x+Anz*CharBreite+1, y+2); Zahl:=Zahl DIV 10; DEC(Anz) UNTIL (Zahl=0) OR (Anz=-1) END DrawInt; (* draw number of Mines to find *) PROCEDURE DrawMinesToFind(f: Frame); BEGIN DrawInt((f.W-119) DIV 2+f.X+2, f.Y+f.H-ObenPlatz+6, f.d.Mines, TRUE); END DrawMinesToFind; (* draw the time *) PROCEDURE DrawTime(f: Frame); BEGIN DrawInt(f.W DIV 2+f.X+16, f.Y+f.H-ObenPlatz+6, (Input.Time()-f.d.Time) DIV TimeUnit, f.d.StartPlay); END DrawTime; (* draw pattern, like mine *) PROCEDURE DrawPat(f: Frame; XKasten, YKasten, No: INTEGER; Mode: BOOLEAN; Color: BOOLEAN; col: INTEGER); VAR dumx, dumy: INTEGER; BEGIN IF Mode THEN ClearKasten(f, XKasten, YKasten, Color) ELSE BlockKasten(f, XKasten, YKasten, Color, col); END; dumx:=f.SeitenOffset+XKasten*KastenPlatz-KastenBreite; dumy:=f.UntenOffset+YKasten*KastenPlatz-KastenBreite; IF Color THEN IF No<3 THEN Display.CopyPattern(black, Pat[1], dumx+2, dumy+2, Display.paint); IF No=2 THEN Display.CopyPattern(red, Pat[2], dumx+2, dumy+2, Display.paint) END ELSE Display.CopyPattern(red, Pat[3], dumx+2, dumy+2, Display.paint); Display.ReplConst(black, dumx+5, dumy+3, 1, 10, Display.replace) END ELSE IF No=1 THEN IF Mode THEN Display.CopyPattern(col, Pat[1], dumx+2, dumy+2, Display.paint) ELSE Display.CopyPattern(Display.black, Pat[1], dumx+2, dumy+2, Display.paint) END ELSE IF No=2 THEN No:=4;END; Display.CopyPattern(Display.black, Pat[No], dumx+2, dumy+2, Display.paint) END END DrawPat; (* invert char *) PROCEDURE DrawCharInv(f: Frame; ch: CHAR; XKasten, YKasten: INTEGER); Pat: Display.Pattern; dx, x, y, w, h: INTEGER; dumx, dumy: INTEGER; BEGIN Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat); dumx:=f.SeitenOffset+XKasten*KastenPlatz-KB+(KB-w) DIV 2; dumy:=f.UntenOffset+YKasten*KastenPlatz-KB+(KB-h) DIV 2; Display.CopyPattern(Display.white, Pat, dumx, dumy, Display.invert); END DrawCharInv; (* make new data *) PROCEDURE NeuesFeld*(d: Data; x, y: INTEGER); ZaehlerX, ZaehlerY: INTEGER; dummy: LONGINT; Bomben: SHORTINT; BEGIN NEW(d.Feld, x+2, y+2); IF d.Feld=NIL THEN d.Aktiv:=FALSE; RETURN; END; FOR ZaehlerX:=0 TO x+1 DO FOR ZaehlerY:=0 TO y+1 DO d.Feld[ZaehlerX, ZaehlerY]:=1 END END; dummy:=(LONG(x)*y*d.Quote) DIV 100; d.Count:=LONG(x)*y-dummy;d.Mines:=dummy; REPEAT REPEAT ZaehlerX:=Random(x)+1; ZaehlerY:=Random(y)+1 UNTIL d.Feld[ZaehlerX, ZaehlerY]=1; d.Feld[ZaehlerX, ZaehlerY]:=10; DEC(dummy) UNTIL dummy=0; FOR ZaehlerX:=1 TO x DO FOR ZaehlerY:=1 TO y DO IF d.Feld[ZaehlerX, ZaehlerY]=1 THEN Bomben:=1; IF d.Feld[ZaehlerX+1, ZaehlerY]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX+1, ZaehlerY+1]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX, ZaehlerY+1]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX-1, ZaehlerY+1]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX-1, ZaehlerY]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX-1, ZaehlerY-1]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX, ZaehlerY-1]=10 THEN INC(Bomben);END; IF d.Feld[ZaehlerX+1, ZaehlerY-1]=10 THEN INC(Bomben);END; d.Feld[ZaehlerX, ZaehlerY]:=Bomben END END END NeuesFeld; (* draw a box *) PROCEDURE DrawKasten*(f: Frame; XZaehler, YZaehler: INTEGER; Color: BOOLEAN; col: INTEGER); VAR dummy: SHORTINT; BEGIN dummy:=f.d.Feld[XZaehler, YZaehler]; IF dummy>0 THEN IF dummy>16 THEN DrawPat(f, XZaehler, YZaehler, 3, FALSE, Color, col) ELSE BlockKasten(f, XZaehler, YZaehler, Color, col) END ELSE IF dummy=-10 THEN DrawPat(f, XZaehler, YZaehler, 1, TRUE, Color, col) ELSIF dummy=-1 THEN ClearKasten(f, XZaehler, YZaehler, Color) ELSE DrawChar(f, CHR(47-dummy), XZaehler, YZaehler, Color, col) END END DrawKasten; (* draw all *) PROCEDURE PlotAll(f: Frame); VAR xdum, ydum: INTEGER; BEGIN xdum:=(f.W-7*KastenPlatz) DIV 2+f.X+2; ydum:=f.Y+f.H-ObenPlatz+6; IF Color THEN Display.ReplConst(lightgray, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace); Display.ReplConst(darkgray, xdum, ydum-1, 4*CharBreite+11, KastenBreite-1, Display.replace); xdum:=f.W DIV 2+f.X+16; Display.ReplConst(lightgray, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace); Display.ReplConst(darkgray, xdum, ydum-1, 4*CharBreite+11, KastenBreite-1, Display.replace) ELSE Display.ReplConst(Display.white, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace); xdum:=f.W DIV 2+f.X+16; Display.ReplConst(Display.white, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace); END; DrawMinesToFind(f); DrawTime(f); ydum:=f.d.YKastenAnz*KastenPlatz+1; xdum:=f.d.XKastenAnz*KastenPlatz+1; IF Color THEN Display.ReplConst(midgray, f.SeitenOffset, f.UntenOffset, xdum, ydum, Display.replace); Display.ReplConst(lightgray, f.SeitenOffset-1, f.UntenOffset-1, 1, ydum+2, Display.replace); Display.ReplConst(lightgray, f.SeitenOffset-1, f.UntenOffset+ydum, xdum+1, 1, Display.replace); Display.ReplConst(darkgray, f.SeitenOffset-1, f.UntenOffset-1, xdum+2, 1, Display.replace); Display.ReplConst(darkgray, f.SeitenOffset+xdum, f.UntenOffset-1, 1, ydum+2, Display.replace) ELSE Display.ReplConst(Display.white, f.SeitenOffset, f.UntenOffset, xdum, ydum, Display.replace); END; FOR xdum:=1 TO f.d.XKastenAnz DO FOR ydum:=1 TO f.d.YKastenAnz DO DrawKasten(f, xdum, ydum, Color, Display.white) END END PlotAll; (* draw all, if finding a mine *) PROCEDURE SwitchAll(f: Frame; Color: BOOLEAN; col: INTEGER); xdum, ydum: INTEGER; Typ: SHORTINT; BEGIN Oberon.RemoveMarks(f.X, f.Y, f.W, f.H); FOR xdum:=1 TO f.d.XKastenAnz DO FOR ydum:=1 TO f.d.YKastenAnz DO Typ:=f.d.Feld[xdum, ydum]; IF Typ>0 THEN IF Typ=10 THEN DrawPat(f, xdum, ydum, 1, FALSE, Color, col) ELSIF Typ<10 THEN f.d.Feld[xdum, ydum]:=-Typ; DrawKasten(f, xdum, ydum, Color, col) ELSIF (Typ>16) & (Typ#26) THEN DrawPat(f, xdum, ydum, 2, FALSE, Color, col) END END END END SwitchAll; (* test if Raster fits to frame *) PROCEDURE TestRaster(f: Frame): BOOLEAN; VAR XMax,YMax: INTEGER; BEGIN XMax:=(f.W-SeitenPlatz*2) DIV KastenPlatz; YMax:=(f.H-ObenPlatz-UntenPlatz) DIV KastenPlatz; IF XMaxd.XKastenAnz) OR (y>d.YKastenAnz) THEN RETURN;END; Dummy:=d.Feld[x, y]; IF (Dummy<0) OR (Dummy>9) THEN RETURN;END; DEC (d.Count); d.Feld[x, y]:=-Dummy; pkmsg.d:=d; pkmsg.x:=x;pkmsg.y:=y; Viewers.Broadcast(pkmsg); IF Dummy=1 THEN SearchMore(d, x+1, y);SearchMore(d, x+1, y+1); SearchMore(d, x,y+1);SearchMore(d, x-1, y+1); SearchMore(d, x-1, y);SearchMore(d, x-1, y-1); SearchMore(d, x, y-1);SearchMore(d, x+1, y-1) END SearchMore; (* new HIScore ? *) PROCEDURE CheckHiScore(d: Data); BEGIN IF d.Mode>-1 THEN IF d.Time0) & (Dummy<16) THEN pkmsg.d:=f.d; pkmsg.x:=XKasten;pkmsg.y:=YKasten; IF Dummy=10 THEN f.d.Feld[XKasten, YKasten]:=-10; f.d.Aktiv:=FALSE; SwitchAll(f, Color, col); Viewers.Broadcast(pkmsg) ELSE IF Dummy=1 THEN SearchMore(f.d, XKasten, YKasten) ELSE f.d.Feld[XKasten, YKasten]:=-Dummy; DEC(f.d.Count); Viewers.Broadcast(pkmsg); END; IF f.d.Count=0 THEN timsg.id:=StartTime; timsg.Count:=0; Viewers.Broadcast(timsg); f.d.Aktiv:=FALSE; f.d.Time:=(Input.Time()-f.d.Time) DIV TimeUnit; CheckHiScore(f.d) END END END SwitchKasten; (* react on mouse keys *) PROCEDURE MouseKeys*(f: Frame; XKasten, YKasten: INTEGER; Key: SET; Color: BOOLEAN; col: INTEGER); Dummy: SHORTINT; pkmsg: PlotKastenMsg; BEGIN Dummy:=f.d.Feld[XKasten, YKasten]; pkmsg.d:=f.d; pkmsg.x:=XKasten;pkmsg.y:=YKasten; IF Key={2} THEN IF ~f.d.StartPlay THEN f.d.StartPlay:=TRUE; f.d.Time:=Input.Time(); END; SwitchKasten(f, XKasten, YKasten, Color, col) ELSIF Key={0} THEN IF Dummy>0 THEN IF Dummy<16 THEN f.d.Feld[XKasten, YKasten]:=Dummy+16; f.d.Mines:=f.d.Mines-1 ELSE f.d.Feld[XKasten, YKasten]:=Dummy-16; f.d.Mines:=f.d.Mines+1; END; Viewers.Broadcast(pkmsg) END ELSIF Key={0,2} THEN IF Dummy<0 THEN IF ~f.d.StartPlay THEN f.d.StartPlay:=TRUE; f.d.Time:=Input.Time(); END; SwitchKasten(f, XKasten+1, YKasten, Color, col); SwitchKasten(f, XKasten+1, YKasten-1, Color, col); SwitchKasten(f, XKasten, YKasten-1, Color, col); SwitchKasten(f, XKasten-1, YKasten-1, Color, col); SwitchKasten(f, XKasten-1, YKasten, Color, col); SwitchKasten(f, XKasten-1, YKasten+1, Color, col); SwitchKasten(f, XKasten, YKasten+1, Color, col); SwitchKasten(f, XKasten+1, YKasten+1, Color, col) END END MouseKeys; (* get selected frame *) PROCEDURE GetFrame(VAR f: Display.Frame): BOOLEAN; VAR v: Viewers.Viewer; BEGIN IF Oberon.Par.frame=Oberon.Par.vwr.dsc THEN IF (Oberon.Par.frame # NIL) THEN f:=Oberon.Par.frame.next; RETURN TRUE END ELSE v:=Oberon.MarkedViewer(); IF (v.dsc # NIL) & (v.dsc.next # NIL) THEN f:=v.dsc.next; RETURN TRUE END END; RETURN FALSE END GetFrame; (* Open new Text-Frame *) PROCEDURE OpenViewer(text: Texts.Text); VAR x, y: INTEGER; v: Viewers.Viewer; cf: TextFrames.Frame; BEGIN Oberon.AllocateSystemViewer(Oberon.Par.vwr.X, x, y); cf := TextFrames.NewText(text, 0); v := MenuViewers.New(TextFrames.NewMenu("Mines Hall Of Fame", "System.Close System.Copy System.Grow"), cf, TextFrames.menuH, x, y) END OpenViewer; (* do the pause *) PROCEDURE DoPause(f: Frame); nfmsg: NeuesFeldMsg; rpmsg: RePlotMsg; pnmsg: PlotNewMsg; BEGIN IF f.d.Pause THEN IF TestRaster(f) OR PauseFlag THEN f.d.Pause:=FALSE; nfmsg.d:=f.d;nfmsg.Change:=FALSE; Viewers.Broadcast(nfmsg); IF nfmsg.Change THEN IF f.d.Aktiv THEN NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz); END; pnmsg.d:=f.d; Viewers.Broadcast(pnmsg); f.d.StartPlay:=FALSE ELSE rpmsg.All:=FALSE; rpmsg.d:=f.d; f.d.Time:=Input.Time()-f.d.Time; Viewers.Broadcast(rpmsg) END ELSE Texts.WriteString(W, "Frame too small for old game !"); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); PauseFlag:=TRUE END ELSE f.d.Pause:=TRUE; f.d.Time:=Input.Time()-f.d.Time; rpmsg.d:=f.d;rpmsg.All:=FALSE; Viewers.Broadcast(rpmsg) END DoPause; (* set Pause mode *) PROCEDURE Pause*; f, g: Display.Frame; BEGIN IF GetFrame(g) THEN f:=g; WITH f: Frame DO IF f.d.Aktiv THEN DoPause(f)END ELSE END END Pause; (* do mouseaction *) PROCEDURE DoMou(f: Frame; X, Y: INTEGER; Key, FirstKey: SET); XKasten, YKasten: INTEGER; XStore, YStore: INTEGER; Dummy: SHORTINT; pnmsg: PlotNewMsg; nfmsg: NeuesFeldMsg; timsg: TimeMsg; BEGIN IF ~f.d.Pause THEN XStore:=X;YStore:=Y; X:=X-f.SeitenOffset;Y:=Y-f.UntenOffset; IF X<0 THEN RETURN;END; IF Y<0 THEN RETURN;END; XKasten:=X DIV KastenPlatz +1; YKasten:=Y DIV KastenPlatz +1; IF (XKasten<=f.d.XKastenAnz) & (YKasten<=f.d.YKastenAnz) THEN IF ~f.d.Aktiv THEN RETURN;END; IF ((X MOD KastenPlatz)=0) OR ((Y MOD KastenPlatz)=0) THEN RETURN; END; Dummy:=f.d.Feld[XKasten, YKasten]; IF Key={1} THEN IF Dummy>0 THEN IF Dummy<16 THEN Oberon.RemoveMarks(f.SeitenOffset, f.UntenOffset, f.W, f.H); DrawCharInv(f, "?", XKasten, YKasten) END END ELSE MouseKeys(f, XKasten, YKasten, Key, Color, Display.white); END; IF f.d.Count=0 THEN GotIt(f) ELSE IF ~UseTimeTask THEN timsg.id:=StartTime; timsg.Count:=0; Viewers.Broadcast(timsg) END END ELSE IF (YStore>f.Y+f.H-ObenPlatz+3) & (YStore0 THEN DrawMinesToFind(self); END; IF ~self.d.Aktiv THEN PlotSmily(self, FALSE)END | m: NeuesFeldMsg DO (* Check if new W & H are fitting to frame *) IF CheckRaster(self) THEN m.Change:=TRUE END ELSE END END END ELSE END Handler; (* get parameters *) PROCEDURE GetPar*(VAR Quote, X, Y, Mode: INTEGER); S: Texts.Scanner; text: Texts.Text; Dummy, StoreQuote: INTEGER; beg, end, time: LONGINT; BEGIN StoreQuote:=Quote; Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); IF S.class=Texts.Char THEN IF S.c="^" THEN Oberon.GetSelection(text, beg, end, time); IF time=-1 THEN RETURN; END; Texts.OpenScanner(S, text, beg); Texts.Scan(S) ELSE RETURN END END; IF S.class=Texts.Int THEN IF (S.i>0) & (S.i<90) THEN; Quote:=SHORT(S.i); IF (Mode=-1) OR (X#256) THEN Texts.Scan(S); IF S.class=Texts.Int THEN; Dummy:=SHORT(S.i); Texts.Scan(S); IF S.class=Texts.Int THEN IF (Dummy<6) OR (Dummy>127) THEN X:=8 ELSE X:=Dummy; END; IF (S.i<6) OR (S.i>127) THEN Y:=8 ELSE Y:=SHORT(S.i) END END END ELSE IF Quote#StoreQuote THEN Mode:=-1 END END END END GetPar; (* set frame and parameters *) PROCEDURE ShortNewPar(X, Y, Quote, Mode: INTEGER); f, g: Display.Frame; nfmsg: NeuesFeldMsg; pnmsg: PlotNewMsg; BEGIN IF GetFrame(g) THEN f:=g; WITH f: Frame DO GetPar(Quote, X, Y, Mode); f.d.Quote:=Quote;f.d.Mode:=Mode; f.d.XKastenAnz:=X;f.d.YKastenAnz:=Y; f.d.Aktiv:=TRUE;f.d.Pause:=FALSE; nfmsg.d:=f.d; Viewers.Broadcast(nfmsg); IF f.d.Aktiv THEN NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz); END; pnmsg.d:=f.d; f.d.StartPlay:=FALSE; Viewers.Broadcast(pnmsg) ELSE END END ShortNewPar; (* Open MenuFrame with Mines.Menu.Text *) PROCEDURE MenuFrame(): TextFrames.Frame; mf: TextFrames.Frame; buf: Texts.Buffer; t: Texts.Text; r: Texts.Reader; end: LONGINT; ch: CHAR; BEGIN IF Files.Old("Mines.Menu.Text")=NIL THEN mf:=TextFrames.NewMenu("Mines", Menu) ELSE mf:=TextFrames.NewMenu("Mines", ""); NEW(t);Texts.Open(t, "Mines.Menu.Text"); Texts.OpenReader(r, t, 0); REPEAT Texts.Read(r, ch) UNTIL r.eot OR (ch=0DX); IF r.eot THEN end:=t.len ELSE end:=Texts.Pos(r)-1; END; NEW(buf); Texts.OpenBuf(buf); Texts.Save(t, 0, end, buf);Texts.Append(mf.text, buf) END; RETURN mf; END MenuFrame; (* set new username *) PROCEDURE SetUser*; S: Texts.Scanner; text: Texts.Text; beg, end, time: LONGINT; BEGIN Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(S); IF S.class=Texts.Char THEN IF S.c="^" THEN Oberon.GetSelection(text, beg, end, time); IF time=-1 THEN RETURN; END; Texts.OpenScanner(S, text, beg); Texts.Scan(S) ELSE RETURN END END; IF S.class=Texts.Name THEN COPY(S.s, Name); END; Texts.WriteString(W, "Current Username : "); Texts.WriteString(W, Name); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); END SetUser; (* show Hi-Score *) PROCEDURE Score*; i: INTEGER; te: Texts.Text; BEGIN te:=TextFrames.Text(""); IF Files.Old("Mines.Score.Text")=NIL THEN Texts.WriteString(W, " Oberon-Mines Hall Of Fame ! ");Texts.WriteLn(W); Texts.WriteString(W, "________________________________________________________");Texts.WriteLn(W) ELSE Texts.Open(te, "Mines.Score.Text"); END; FOR i:=0 TO 2 DO IF i=0 THEN Texts.WriteString(W, "Beginner") ELSIF i=1 THEN Texts.WriteString(W, "Advanced") ELSE Texts.WriteString(W, "Expert");END; Texts.Write(W, CHR(9)); Texts.WriteInt(W, HiTime[i], 1); Texts.WriteString(W, " sec"); Texts.Write(W, CHR(9)); Texts.WriteString(W, HiName[i]); Texts.WriteLn(W); END; Texts.WriteLn(W); Texts.WriteString(W, "Current Username : "); Texts.WriteString(W, Name); Texts.WriteLn(W); Texts.Append(te, W.buf); OpenViewer(te); END Score; (* create new frame with new data *) PROCEDURE Open*; x, y: INTEGER; f: Frame; v: MenuViewers.Viewer; BEGIN NEW(f);IF f=NIL THEN RETURN;END; NEW(f.d);IF f.d=NIL THEN RETURN;END; f.handle:=Handler;f.d.Aktiv:=TRUE;f.d.Quote:=16; f.LastModMsg:=TRUE;f.d.Pause:=FALSE; f.d.XKastenAnz:=256;f.d.YKastenAnz:=256; f.d.Mode:=-1;f.d.StartPlay:=FALSE; Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y); v:=MenuViewers.New(MenuFrame(), f, TextFrames.menuH, x, y); END Open; (* switch between color ans b/w mode *) PROCEDURE ColorMode*; VAR rpmsg: RePlotMsg; BEGIN Color:=~Color; rpmsg.All:=TRUE; Viewers.Broadcast(rpmsg); SaveHi(FALSE); END ColorMode; (* switches between task und mouse action time mode *) PROCEDURE TimeMode*; BEGIN UseTimeTask:=~UseTimeTask; IF UseTimeTask THEN IF ~TimeTaskRuns THEN StartTask() END ELSE IF TimeTaskRuns THEN StopTask() END END; SaveHi(FALSE); END TimeMode; (* start different types of the game *) PROCEDURE Beginner*; BEGIN ShortNewPar(8, 8, 15, 0); END Beginner; PROCEDURE Advanced*; BEGIN ShortNewPar(16, 16, 16, 1); END Advanced; PROCEDURE Expert*; BEGIN ShortNewPar(30, 16, 21, 2); END Expert; PROCEDURE Max*; BEGIN ShortNewPar(256, 256, 16, -1); END Max; PROCEDURE Start*; BEGIN ShortNewPar(8, 8, 16, -1); END Start; BEGIN TimeUnit:=Input.TimeUnit; (* replace Input.TimeUnit by 300 at MacOberon and Ceres *) UsedFont:=Fonts.This("Syntax14.Scn.Fnt"); Texts.OpenWriter(W); Texts.WriteString(W, "Oberon-Mines V1.32"); Texts.WriteLn(W); Texts.WriteString(W, "(C) 1 Oct 95 by Ralf Degner"); Texts.WriteLn(W); Texts.Append(Oberon.Log, W.buf); StartTime:=Input.Time(); seed:=StartTime; TimeTaskRuns:=FALSE; Color:=FALSE;UseTimeTask:=TRUE; IF Oberon.User="" THEN Name:="AMIGA" ELSE COPY(Oberon.User, Name); END; Colors[0]:=Col1;Colors[1]:=Col2;Colors[2]:=Col3;Colors[3]:=Col4; Colors[4]:=Col5;Colors[5]:=Col6;Colors[6]:=Col7;Colors[7]:=Col8; LoadHi(); (* install patterns *) HappyData[1]:={5,6,7,8,9,10}; HappyData[2]:={3,4,11,12}; HappyData[3]:={2,13}; HappyData[4]:={1,5,6,7,8,9,10,14}; HappyData[5]:={1,4,11,14}; HappyData[6]:={0,3,12,15}; HappyData[7]:={0,7,8,15}; HappyData[8]:={0,7,8,15}; HappyData[9]:={0,15}; HappyData[10]:={0,15}; HappyData[11]:={0,15,5,6,9,10}; HappyData[12]:={1,14,5,6,9,10}; HappyData[13]:={1,14}; HappyData[14]:={2,13}; HappyData[15]:={3,4,11,12}; HappyData[16]:={5,6,7,8,9,10}; HappyPat:=Display.NewPattern(HappyData, 16, 16); SadData:=HappyData; SadData[5]:={1,5,6,7,8,9,10,14}; SadData[4]:={1,4,11,14}; SadData[6]:={0,15}; SadPat:=Display.NewPattern(SadData, 16, 16); BackData[1]:={}; BackData[2]:={5,6,7,8,9,10}; BackData[3]:={3,4,5,6,7,8,9,10,11,12}; BackData[4]:={2,3,4,5,6,7,8,9,10,11,12,13}; BackData[5]:={2,3,4,5,6,7,8,9,10,11,12,13}; BackData[6]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14}; BackData[7]:={1,2,3,4,5,6,9,10,11,12,13,14}; BackData[8]:={1,2,3,4,5,6,9,10,11,12,13,14}; BackData[9]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14}; BackData[10]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14}; BackData[11]:={1,2,3,4,7,8,11,12,13,14}; BackData[12]:={1,2,3,4,7,8,11,12,13,14}; BackData[13]:={2,3,4,5,6,7,8,9,10,11,12,13}; BackData[14]:={3,4,5,6,7,8,9,10,11,12}; BackData[15]:={5,6,7,8,9,10}; BackData[16]:={}; BackPat:=Display.NewPattern(BackData, 16, 16); GotItData:=HappyData; GotItData[12]:={1,4,5,6,7,8,9,10,11,14}; GotItData[11]:={0,3,4,5,6,9,10,11,12,15}; GotItData[10]:={0,2,4,5,6,9,10,11,13,15}; GotItData[9]:={0,1,5,6,7,8,9,10,14,15}; GotItPat:=Display.NewPattern(GotItData, 16, 16); PauseData:=SadData; PauseData[5]:={1,14}; PauseData[4]:={1,4,5,6,7,8,9,10,11,14}; PausePat:=Display.NewPattern(PauseData, 16, 16); (* Mine *) Data1[1]:={3,4,5,6,7,8}; Data1[2]:={2,3,4,5,6,7,8,9}; Data1[3]:={1,2,3,5,6,7,8,9,10}; Data1[4]:={1,2,5,6,7,8,9,10}; Data1[5]:={1,2,4,5,6,7,8,9,10}; Data1[6]:={1,2,3,4,5,6,7,8,9,10}; Data1[7]:={2,3,4,5,6,7,8,9}; Data1[8]:={3,4,5,6,7,8}; Data1[9]:={5,6}; Data1[10]:={5}; Data1[11]:={6,10}; Data1[12]:={7,8,9}; Pat[1]:=Display.NewPattern(Data1, 12, 12); (* No Mine *) Data2[1]:={0,11}; Data2[2]:={1,10}; Data2[3]:={2,9}; Data2[4]:={3,8}; Data2[5]:={4,7}; Data2[6]:={5,6}; Data2[7]:={5,6}; Data2[8]:={4,7}; Data2[9]:={3,8}; Data2[10]:={2,9}; Data2[11]:={1,10}; Data2[12]:={0,11}; Pat[2]:=Display.NewPattern(Data2, 12, 12); (* Flag *) Data3[1]:={}; Data3[2]:={3}; Data3[3]:={3}; Data3[4]:={3}; Data3[5]:={3}; Data3[6]:={3}; Data3[7]:={3,4,5}; Data3[8]:={3,4,5,6,7}; Data3[9]:={3,4,5,6,7,8,9}; Data3[10]:={3,4,5,6,7}; Data3[11]:={3,4,5}; Data3[12]:={}; Pat[3]:=Display.NewPattern(Data3, 12, 12); (* No Mine - No Color *) FOR Dummy:=1 TO 12 DO Data4[Dummy]:=Data1[Dummy]/Data2[Dummy]; END; Pat[4]:=Display.NewPattern(Data4, 12, 12) END Mines.Open System.Free MinesElems Mines ~